/*
 * VariableStringSerializer_gtest.cpp
 *
 *  Created on: Nov 20, 2012
 *      Author: m
 */

#include <gtest/gtest.h>
#include <string>
#include "../physical_layer/serializers/VariableStringSerializer.h"

using physical::byte;
using physical::VariableStringSerializer;
using std::string;

class VariableStringSerializerTestFixture : public ::testing::Test
{
public:
    VariableStringSerializerTestFixture() :
            m_byteArray( new physical::byte[10240] )
    {
        // initialization code here
    }

    void SetUp()
    {
        // code here will execute just before the test ensues
    }

    void TearDown()
    {
        // code here will be called just after the test completes
        // ok to through exceptions from here if need be
    }

    ~VariableStringSerializerTestFixture()
    {
        // cleanup any pending stuff, but no exceptions allowed

        delete[] m_byteArray;
    }

    // put in any custom data members that you need

    VariableStringSerializer m_serializer;
    byte* m_byteArray;
};

/**
 * Pruebas con un String vacio
 */
TEST_F ( VariableStringSerializerTestFixture, EmptyString )
{
    string anEmptyString;
    string deserializedString;
    size_t serializationSize;
    size_t exectedSerializationSize;
    byte expectedSerialization[1] = { 0 };

    // Configuro los valores esperados
    exectedSerializationSize = 1;
    expectedSerialization[0] = 0;

    // Verifico que el tamaño de serialización sea correcto
    ASSERT_EQ( m_serializer.getSize( anEmptyString ),
            exectedSerializationSize );

    //Serializo y verifico que el resultado sea el esperado
    serializationSize = m_serializer.serialize( anEmptyString, m_byteArray );

    ASSERT_EQ( serializationSize, exectedSerializationSize );
    ASSERT_EQ(
            memcmp( m_byteArray, expectedSerialization, exectedSerializationSize ), 0 );

    // Deserializo y verifico que el resultado sea correcto
    serializationSize = m_serializer.deserialize( expectedSerialization,
            deserializedString );

    ASSERT_EQ( serializationSize, exectedSerializationSize );
    ASSERT_EQ( deserializedString, anEmptyString );
}

/**
 * Pruebas con un String de tamaño menor a 255
 */
TEST_F ( VariableStringSerializerTestFixture, StringWithLengthLowerThan256 )
{
    string aString;
    string deserializedString;
    size_t serializationSize;
    size_t exectedSerializationSize;
    byte expectedSerialization[256];

    // Configuro los valores esperados
    aString.assign( "hola pepe como andas" );
    exectedSerializationSize = aString.length() + 1;
    expectedSerialization[0] = aString.length();
    memcpy( expectedSerialization+1 , aString.c_str(), aString.length() );

    // Verifico que el tamaño de serialización sea correcto
    ASSERT_EQ( m_serializer.getSize( aString ), exectedSerializationSize );

    //Serializo y verifico que el resultado sea el esperado
    serializationSize = m_serializer.serialize( aString, m_byteArray );

    ASSERT_EQ( serializationSize, exectedSerializationSize );
    ASSERT_EQ(
            memcmp( m_byteArray, expectedSerialization, exectedSerializationSize ), 0 );

    // Deserializo y verifico que el resultado sea correcto
    serializationSize = m_serializer.deserialize( expectedSerialization,
            deserializedString );

    ASSERT_EQ( serializationSize, exectedSerializationSize );
    ASSERT_EQ( deserializedString, aString );
}

/**
 * Pruebas con un String de tamaño mayor a 255
 */
TEST_F ( VariableStringSerializerTestFixture, StringWithLengthGreaterThan256 )
{
    string aLongString(
            "este string es muy largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo largo largo largo largo \
            largo largo largo" );

    // Verifico que tire una exception
    ASSERT_THROW( m_serializer.serialize( aLongString, m_byteArray ),
            VariableStringSerializer::StringIsTooLongException );
}
